#pragma once

MS_ALIGN(16) class Vector4
{
public:
	float X, Y, Z, W;

	Vector4(const Vector3& v,float w = 1.0f) : X(v.X), Y(v.Y), Z(v.Z), W(w) {}
	Vector4(const Vector4& v) : X(v.X), Y(v.Y), Z(v.Z), W(v.W) {}
	explicit Vector4(float x = 0.0f, float y = 0.0f, float z = 0.0f, float w = 1.0f) : X(x), Y(y), Z(z), W(w) {}

	// Unary operators.
	Vector4 operator-() const { return Vector4( -X, -Y, -Z, -W ); }

	// Binary math operators.
	Vector4 operator+( const Vector4& V ) const { return Vector4( X + V.X, Y + V.Y, Z + V.Z, W + V.W ); }
	Vector4 operator-( const Vector4& V ) const { return Vector4( X - V.X, Y - V.Y, Z - V.Z, W - V.W ); }
	Vector4 operator*( float Scale ) const { return Vector4( X * Scale, Y * Scale, Z * Scale, W * Scale ); }
	Vector4 operator/( float Scale ) const { const float RScale = 1.f/Scale; return Vector4( X * RScale, Y * RScale, Z * RScale, W * RScale ); }
	Vector4 operator*( const Vector4& V ) const { return Vector4( X * V.X, Y * V.Y, Z * V.Z, W * V.W ); }

	// Simple functions.
	float* Ptr() { return &X; }
	const float* Ptr() const { return &X; }
	float& Component( int Index ) { return (&X)[Index]; }
	friend float Dot3( const Vector4& V1, const Vector4& V2 ) { return V1.X*V2.X + V1.Y*V2.Y + V1.Z*V2.Z; }
	friend float Dot4( const Vector4& V1, const Vector4& V2 ) { return V1.X*V2.X + V1.Y*V2.Y + V1.Z*V2.Z + V1.W*V2.W; }
	friend Vector4 operator*( float Scale, const Vector4& V ) { return V.operator*( Scale ); }

} GCC_ALIGN(16);